/**
 * 
 */
package com.vision.sales.collection.cl.ui;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.i18n.client.HasDirection.Direction;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant;
import com.sencha.gxt.core.client.IdentityValueProvider;
import com.sencha.gxt.core.client.Style.SelectionMode;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer;
import com.sencha.gxt.widget.core.client.event.BeforeStartEditEvent;
import com.sencha.gxt.widget.core.client.event.BeforeStartEditEvent.BeforeStartEditHandler;
import com.sencha.gxt.widget.core.client.event.CompleteEditEvent;
import com.sencha.gxt.widget.core.client.event.CompleteEditEvent.CompleteEditHandler;
import com.sencha.gxt.widget.core.client.form.NumberField;
import com.sencha.gxt.widget.core.client.form.NumberPropertyEditor.DoublePropertyEditor;
import com.sencha.gxt.widget.core.client.grid.AggregationNumberSummaryRenderer;
import com.sencha.gxt.widget.core.client.grid.AggregationRowConfig;
import com.sencha.gxt.widget.core.client.grid.AggregationSafeHtmlRenderer;
import com.sencha.gxt.widget.core.client.grid.CheckBoxSelectionModel;
import com.sencha.gxt.widget.core.client.grid.ColumnConfig;
import com.sencha.gxt.widget.core.client.grid.ColumnModel;
import com.sencha.gxt.widget.core.client.grid.Grid;
import com.sencha.gxt.widget.core.client.grid.Grid.GridCell;
import com.sencha.gxt.widget.core.client.grid.GridView;
import com.sencha.gxt.widget.core.client.grid.SummaryType.SumSummaryType;
import com.sencha.gxt.widget.core.client.grid.editing.GridInlineEditing;
import com.vision.core.cl.ui.UI;
import com.vision.core.cl.ui.component.BasicGridView;
import com.vision.sales.cl.data.CollectionItemProperties;
import com.vision.sales.cl.ui.CustomCheckBoxSelectionModel;
import com.vision.sales.cm.db.data.CollectionItem;

/**
 * @author Mark
 *
 */
public class EditableCollectionItemGridPanel extends VerticalLayoutContainer {
	
	static final NumberFormat DECIMAL_FORMAT = NumberFormat.getFormat("#,##0.00");
	
	ColumnConfig<CollectionItem, String> salesInvoiceNoCol;
	ColumnConfig<CollectionItem, Double> grossSalesCol;
	ColumnConfig<CollectionItem, Double> balanceCol;
	
	ColumnConfig<CollectionItem, Double> paymentCol;
	
	ColumnConfig<CollectionItem, Double> overrunsCol;
	ColumnConfig<CollectionItem, Double> overpaymentsCol;
	ColumnConfig<CollectionItem, Double> discountsCol;
	ColumnConfig<CollectionItem, Double> rejectsCol;
	ColumnConfig<CollectionItem, Double> returnsCol;
	ColumnConfig<CollectionItem, Double> subtotalCol;
	ColumnConfig<CollectionItem, Double> taxCol;
	ColumnConfig<CollectionItem, Double> netAmountCol;
	
	Grid<CollectionItem> grid;
	GridInlineEditing<CollectionItem> editing;
	
	public EditableCollectionItemGridPanel() {
		initializeComponents();
		initializeActions();
	}
	
	private void initializeComponents() {
		List<ColumnConfig<CollectionItem, ?>> columns = new ArrayList<ColumnConfig<CollectionItem, ?>>();
		
		CollectionItemProperties props = CollectionItemProperties.INSTANCE;
		
		IdentityValueProvider<CollectionItem> identity = new IdentityValueProvider<CollectionItem>();
		CheckBoxSelectionModel<CollectionItem> sm = new CustomCheckBoxSelectionModel<CollectionItem>(identity);
		sm.setSelectionMode(SelectionMode.MULTI);

		AbstractCell<Double> decimalCell = UI.decimalCell();
		
		columns.add(sm.getColumn());
		columns.add(UI.column(props.salesInvoiceDate(), 70, "Inv. Date", UI.dateCell()));
		columns.add(salesInvoiceNoCol = UI.column(props.salesInvoiceGroupAndNo(), 80, "Inv. No."));
		
		columns.add(grossSalesCol = UI.column(props.grossSales(), 85, "Gross Sales", decimalCell, HasHorizontalAlignment.ALIGN_RIGHT));
		columns.add(balanceCol = UI.column(props.balance(), 85, "Balance", decimalCell, HasHorizontalAlignment.ALIGN_RIGHT));
		columns.add(paymentCol = UI.column(props.amount(), 85, "Amount", decimalCell, HasHorizontalAlignment.ALIGN_RIGHT));
		columns.add(overrunsCol = UI.column(props.overruns(), 75, "Overruns", decimalCell, HasHorizontalAlignment.ALIGN_RIGHT));
		columns.add(overpaymentsCol = UI.column(props.overpayments(), 75, "Overpayments", decimalCell, HasHorizontalAlignment.ALIGN_RIGHT));
		columns.add(discountsCol = UI.column(props.discounts(), 75, "Discounts", decimalCell, HasHorizontalAlignment.ALIGN_RIGHT));
		columns.add(rejectsCol = UI.column(props.rejects(), 75, "Rejects", decimalCell, HasHorizontalAlignment.ALIGN_RIGHT));
		columns.add(returnsCol = UI.column(props.returns(), 75, "Returns", decimalCell, HasHorizontalAlignment.ALIGN_RIGHT));
		columns.add(subtotalCol = UI.column(props.subtotal(), 85, "Subtotal", decimalCell, HasHorizontalAlignment.ALIGN_RIGHT));
		columns.add(taxCol = UI.column(props.tax(), 65, "Tax", decimalCell, HasHorizontalAlignment.ALIGN_RIGHT));
		columns.add(netAmountCol = UI.column(props.netAmount(), 85, "Net Amount", decimalCell, HasHorizontalAlignment.ALIGN_RIGHT));
		
		for (int i = 3; i < columns.size(); i++) {
			columns.get(i).setAlignment(HorizontalAlignmentConstant.endOf(Direction.LTR));
		}
		
		ColumnModel<CollectionItem> cm = new ColumnModel<CollectionItem>(columns);
		
		GridView<CollectionItem> view = new BasicGridView<CollectionItem>();
		view.setEmptyText("There are no collection items to display.");

		grid = new Grid<CollectionItem>(new ListStore<CollectionItem>(props.key()), cm, view);
		grid.setAllowTextSelection(false);
		grid.setSelectionModel(sm);
		add(grid, new VerticalLayoutData(1, 1));
		
		// Aggregation
		AggregationRowConfig<CollectionItem> total = new AggregationRowConfig<CollectionItem>();
		total.setRenderer(salesInvoiceNoCol, new AggregationSafeHtmlRenderer<CollectionItem>(SafeHtmlUtils.fromTrustedString("<b>TOTAL</b>")));
		AggregationNumberSummaryRenderer<CollectionItem, Double> renderer = new AggregationNumberSummaryRenderer<CollectionItem, Double>(DECIMAL_FORMAT, new SumSummaryType<Double>()) {
//			@Override
//			public SafeHtml render(int colIndex, Grid<CollectionItem> grid) {
//				SafeHtml s = super.render(colIndex, grid);
//				return SafeHtmlUtils.fromTrustedString("<b>" + s.asString() + "</b>");
//			}
		};
	    total.setRenderer(paymentCol, renderer);
	    total.setRenderer(overpaymentsCol, renderer);
	    total.setRenderer(overrunsCol, renderer);
	    total.setRenderer(discountsCol, renderer);
	    total.setRenderer(rejectsCol, renderer);
	    total.setRenderer(returnsCol, renderer);
	    total.setRenderer(subtotalCol, renderer);
	    total.setRenderer(taxCol, renderer);
	    total.setRenderer(netAmountCol, renderer);
	    cm.addAggregationRow(total);
		
		// Editing
		editing = new GridInlineEditing<CollectionItem>(grid);
		
		DoublePropertyEditor propEditor = UI.doubleEditor();
		NumberField<Double> field = new NumberField<Double>(propEditor);
		field.setClearValueOnParseError(true);
		
		editing.addEditor(paymentCol, field);
		editing.addEditor(overpaymentsCol, field);
		editing.addEditor(overrunsCol, field);
		editing.addEditor(discountsCol, field);
		editing.addEditor(rejectsCol, field);
		editing.addEditor(returnsCol, field);
		editing.addEditor(taxCol, field);
	}
	
	private void initializeActions() {
		editing.addBeforeStartEditHandler(new BeforeStartEditHandler<CollectionItem>() {
			@Override
			public void onBeforeStartEdit(BeforeStartEditEvent<CollectionItem> event) {
				GridCell cell = event.getEditCell(); 
				CollectionItem item = grid.getStore().get(cell.getRow());
				if (!grid.getSelectionModel().isSelected(item)) {
					editing.cancelEditing();
					return;
				}
			}
		});
		
		editing.addCompleteEditHandler(new CompleteEditHandler<CollectionItem>() {
			@Override
			public void onCompleteEdit(CompleteEditEvent<CollectionItem> event) {
				GridCell cell = event.getEditCell();
				int col = cell.getCol();
				// If the editted value is the tax, indicate that it is manually overridden
				if (col == grid.getColumnModel().indexOf(taxCol)) {
					CollectionItem item = grid.getStore().get(cell.getRow());
					item.setTaxOverridden(true);
				}
				
				grid.getStore().commitChanges();
			}
		});
	}
	
	ListStore<CollectionItem> getStore() {
		return grid.getStore();
	}

}
